/*
	Copyright 2007-2010 Petr Ohlidal

	This file is a part of GrobMaker

	GrobMaker is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	GrobMaker is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with GrobMaker.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef GROBMAKER_IMAGE
#define GROBMAKER_IMAGE

/** @file */

#include "../Global.hpp"
#include "../Exception.hpp"
#include "../Util/Rectangle.hpp"
#include "../Util/Area.hpp"
#include "../Util/Rectangle.hpp"
#include "../Util/StringUtils.hpp"
#include "AreaFinder.hpp"

namespace GrobMaker{

/**
* @brief An image.
*/
class Image{
	public:

	Image( const fs::path& path, ::FREE_IMAGE_FORMAT format, int flags ){
		this->load(path,format,flags);
	}

	Image(){
		this->pic=NULL;
	};

	Image( const fs::path& path ){
		this->load(path);
	}
	~Image();

	/**
	* Saves the image to path.
	* @return 0 on success, negative number on error.
	*/
	void save(const fs::path& path, FREE_IMAGE_FORMAT format, int flags=0);

	fs::path& getPath(){
		return this->sourcePath;
	}

	unsigned int getWidth(){
		return FreeImage_GetWidth(this->pic);
	}

	unsigned int getHeight(){
		return FreeImage_GetHeight(this->pic);
	}

	std::string getExtension(){
		return this->sourcePath.extension();
	}

	/**
	* Tells if the extension identifies an image format and recognizes the format.
	* @param ext The file extension to be recognized.
	* @param format FreeImage format of the image.
	* @return True if the extension belongs to an image, false otherwise.
	*/
	static bool resolveExtension(std::string ext, FREE_IMAGE_FORMAT* format=NULL);

	static bool resolveExtension( const fs::path& path, ::FREE_IMAGE_FORMAT* format=NULL ){
		std::string ext = StringUtils::getExtensionNoDot(path);
		return resolveExtension( ext, format );
	}

	/**
	* Returns a rectangle surrounding a specific portion of the bitmap.
	* Uses an AreaFinder class to locate the area.
	* @param area The rectangle to be written.
	* @param finder The AreaFinder to locate the requested area.
	* @return true if area was found, false otherwise.
	*/
	bool findAreaRect( Rectangle& area, const AreaFinder& finder ) const;

	bool findArea( Area& area, const AreaFinder& finder ) const{
		Rectangle r;
		bool found = this->findAreaRect( r, finder );
		if(found){
			area.x = static_cast<float>(r.x);
			area.y = static_cast<float>(r.y);
			area.w = static_cast<float>(r.w);
			area.h = static_cast<float>(r.h);
		}
		return found;
	}

	/**
	* Trims the image by given area.
	* @return true on success, false if the area is larger than original image.
	*/
	void trim( Rectangle& area );

	FIBITMAP* getBitmap(){
		return this->pic;
	}

	void setBitmap( FIBITMAP* bitmap ){
		if( this->pic ){
			this->unload();
		}
		this->pic = bitmap;
	}

	void unload(){
		if( this->pic != NULL ){
			FreeImage_Unload(this->pic);
			this->pic=NULL;
		}
	}

	/**
	* Scales the image. If either of the params is zero, it'll be computed
	* to keep ascpect ratio.
	*/
	void scale( int w, int h );

	/**
	* @brief Parses shadow images.
	* @param img The image to be transformed.
	* Full black areas of the source get 'shadowAlpha' value, other shades are computed
	*/
	static void parseShadowSprite( Image& img, float shadowAlpha );
	private:
	FIBITMAP* pic;
	fs::path sourcePath;
	void load( const fs::path& path, FREE_IMAGE_FORMAT format, int flags=0);
	void load( const fs::path& path ){
		FREE_IMAGE_FORMAT format;
		if( Image::resolveExtension(path, &format)==true ){
			this->load( path, format, 0 );
		}
		else{
			std::stringstream msg;
			msg<<"Image::load(): unknown image extension '"<<path.extension()<<"' in file '"<<path<<"'";
			throw Exception(msg);
		}
	}


};

} // namespace GrobMaker

#endif //#ifndef GROBMAKER_IMAGE
